package cn.whx.hrm.service.impl;

import cn.whx.hrm.domain.CourseType;
import cn.whx.hrm.mapper.CourseTypeMapper;
import cn.whx.hrm.service.ICourseTypeService;
import cn.whx.hrm.util.AjaxResult;
import cn.whx.hrm.vo.CrumbVo;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 课程目录 服务实现类
 * </p>
 *
 * @author whx
 * @since 2021-06-21
 */
@Service
public class CourseTypeServiceImpl extends ServiceImpl<CourseTypeMapper, CourseType> implements ICourseTypeService {
    @Autowired
    private CourseTypeMapper courseTypeMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private static ReentrantLock lock = new ReentrantLock();
    @Override
    public AjaxResult treeData() {
        List<CourseType> courseTypes = new ArrayList<>();
        Object cache = redisTemplate.opsForValue().get("course_type_tree_data");
        if (cache !=null){//缓存中有的话
            courseTypes = (List<CourseType>) cache;//嗯转
            System.out.println("redis里面");
        }else {//没有的话从数据库里面拿
            if (lock.tryLock()){
                try {
                    courseTypes = threeType();
                    //随机事件
                    int i = ThreadLocalRandom.current().nextInt(10, 100);
                    //存入缓存 设置随机时间解决雪崩
                    redisTemplate.opsForValue().set("course_type_tree_data", courseTypes,i , TimeUnit.MINUTES );
                    System.out.println("数据库里面");
                } finally {
                    //释放锁
                    lock.unlock();
                }
            }else {
                //睡一会儿
                try {
                    Thread.sleep(100l);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                treeData();

            }

        }
        return AjaxResult.me().setResultObj(courseTypes);
    }

    @Override
    public List<CrumbVo> crumbs(Long id) {
        ArrayList<CrumbVo> list = new ArrayList<>();
        //根据id获取到path，获取所有类
        CourseType courseType = courseTypeMapper.selectById(id);
        String path = courseType.getPath();
        //用.分割
        String[] ids = path.split("\\.");
        for (String tid:ids){
            CrumbVo crumbVo = new CrumbVo();
            Long pathId = Long.valueOf(tid);
            //根据pathId获取自己,再用pid获取自己的同级
            CourseType own = courseTypeMapper.selectById(pathId);
            EntityWrapper<CourseType> wrapper = new EntityWrapper<>();
            wrapper.eq("pid", own.getPid());//获取同级
            wrapper.and().ne("id", own.getId());//剔除自己
            List<CourseType> bros = courseTypeMapper.selectList(wrapper);
            //添加自己和兄弟
            crumbVo.setOwn(own);
            crumbVo.setBros(bros);
            //添加到返回结果
            list.add(crumbVo);
        }
        return list;
    }

    @Override
    public boolean insert(CourseType entity) {
        //第一次删除
        redisTemplate.delete("course_type_tree_data");
        //更新数据库
        boolean insert = super.insert(entity);
        //延时
        try {
            Thread.sleep(100L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //第二次删除
        redisTemplate.delete("course_type_tree_data");
        return insert;
    }

    @Override
    public boolean update(CourseType entity, Wrapper<CourseType> wrapper) {
        redisTemplate.delete("course_type_tree_data");
        return super.update(entity, wrapper);
    }

    @Override
    public boolean deleteById(Serializable id) {
        redisTemplate.delete("course_type_tree_data");
        return super.deleteById(id);
    }

    private List<CourseType> threeType() {
        List<CourseType> list = new ArrayList<>();
        //查询出所有东西
        List<CourseType> courseTypes = courseTypeMapper.selectList(null);
        HashMap<Long, CourseType> map = new HashMap<>();
        //id和对象的关系
        courseTypes.forEach(courseType -> {
            map.put(courseType.getId(), courseType);
        });
        //找爹，遍历数据
        courseTypes.stream().forEach(son -> {
            if (son.getPid()==0){ //找到最顶级 pid = 0
                //添加到里面去
                list.add(son);
            }else {//其他级别  pid要是和他id相等 就找到爹了
                CourseType courseType = map.get(son.getPid());
                //添加到子属性里去
                courseType.getChildren().add(son);
            }
        });
        return  list;
    }
}
